﻿using System;
using BasecampRestAPI;
using NUnit.Framework;
using TestBasecampRestAPI.Fakes;

namespace TestBasecampRestAPI
{
	[TestFixture]
	public class TestProject : TestProjectBaseFixture
	{
		[Test]
		public void Construct()
		{
			Assert.AreEqual(6969, _project.Id);
			Assert.AreEqual("FakeProject", _project.Name);
			Assert.AreEqual(new DateTime(1969, 12, 03, 16, 45, 45), _project.CreatedOn);
			Assert.AreEqual(new DateTime(1977, 12, 03, 16, 45, 45), _project.LastChangedOn);
			Assert.AreEqual("Flag day for all users", _project.Announcement);
			Assert.AreEqual("Open", _project.Status);
			Assert.AreEqual("1", _project.StartPage);
			Assert.AreEqual(true, _project.ShowWriteBoards);
			Assert.AreEqual(true, _project.ShowAnnouncement);
		}

		[Test]
		public void GetPeople()
		{
			SetupResponseXml(Properties.Resources.FakePeople);
			IPerson[] people = _project.People;
			Assert.IsNotNull(people);
			Assert.AreEqual(2, people.Length);
			Assert.AreEqual(TestBasecamp.Person1Id, people[0].Id);
			Assert.AreEqual(TestBasecamp.Person2Id, people[1].Id);
		}

		[Test]
		public void GetToDoListsEmptyList()
		{
			SetupResponseXml("<todo-lists></todo-lists>");
			IToDoList[] lists = _project.ToDoLists;
			Assert.IsNotNull(lists);
			Assert.AreEqual(0, lists.Length);
			AssertLastGetRequestForAction("todo_lists.xml?filter=all");
		}

		[Test]
		public void GetMilestonesEmptyList()
		{
			SetupResponseXml("<milestones type=\"array\"></milestones>");
			IMilestone[] milestones = _project.Milestones;
			Assert.IsNotNull(milestones);
			Assert.AreEqual(0, milestones.Length);
			AssertLastGetRequestForAction("milestones/list.xml");
			Assert.AreEqual("<request/>", _service.GetRequestResponseElementLastData);
		}

		[Test]
		public void GetMilestoneById()
		{
			SetupResponseXml(
				string.Format("<milestones type=\"array\">{0}</milestones>", Properties.Resources.FakeMilestone));
			const int milestoneId = 10808780;
			IMilestone milestone = _project.GetMilestoneById(milestoneId);
			Assert.IsNotNull(milestone);
			Assert.AreEqual(milestoneId, milestone.Id);
			Assert.IsTrue(_service.GetRequestResponseElementCalled);
		}

		[Test]
		public void GetCategoriesForTypePost()
		{
			SetupResponseXml(Properties.Resources.FakeCategories);
			ICategory[] categories = _project.GetCategoriesForType(CategoryType.Post);
			Assert.IsNotNull(categories);
			Assert.AreEqual(2, categories.Length);
			Assert.AreEqual(1366, categories[0].Id);
			Assert.AreEqual(1367, categories[1].Id);
			AssertGetRequestForAction("categories.xml?type=post");
		}

		[Test]
		public void GetRecentMessages()
		{
			SetupResponseXml(Properties.Resources.FakePosts);
			IPost[] messages = _project.RecentMessages;
			AssertGetRequestForAction("posts.xml");
			AssertMessagesHaveIds(messages, 4404, 4405);
		}

		[Test]
		public void GetArchivedMessages()
		{
			SetupResponseXml(Properties.Resources.FakePosts);
			IPost[] messages = _project.ArchivedMessages;
			AssertMessagesHaveIds(messages, 4404, 4405);
		}

		[Test]
		public void GetMessagesForCategory()
		{
			SetupResponseXml(Properties.Resources.FakePosts);
			FakeCategory category = new FakeCategory { Id = 1366 };
			IPost[] messages = _project.GetMessagesForCategory(category);
			AssertMessagesHaveIds(messages, 4404, 4405);
		}

		[Test]
		public void GetArchivedMessagesForCategory()
		{
			SetupResponseXml(Properties.Resources.FakePosts);
			FakeCategory category = new FakeCategory { Id = 1366 };
			IPost[] messages = _project.GetArchivedMessagesForCategory(category);
			AssertMessagesHaveIds(messages, 4404, 4405);
		}

		[Test]
		public void PathForId()
		{
			Assert.AreEqual("projects/1336.xml", Project.PathForId(1336));
		}

		private static void AssertMessagesHaveIds(IPost[] messages, params int[] ids)
		{
			Assert.IsNotNull(messages);
			Assert.AreEqual(ids.Length, messages.Length);
			for (int i = 0; i < ids.Length; ++i)
			{
				Assert.AreEqual(ids[i], messages[i].Id);
			}
		}

		private void AssertLastGetRequestForAction(string action)
		{
			Assert.IsTrue(_service.GetRequestResponseElementCalled);
			Assert.AreEqual(String.Format("projects/{0}/" + action, _project.Id),
							_service.GetRequestResponseElementLastRequestPath);
		}
	}
}
